import os
from typing import Any
from fastapi import Header, HTTPException
from jose import jwt, JWTError
from datetime import datetime, timedelta, timezone

from api.login.login import GetUserid, GetUser_acl, GetUser_proper

# 从环境变量中获取SECRET_KEY和ALGORITHM
SECRET_KEY = os.getenv("SECRET_KEY", "zhujie")  # 密钥
ALGORITHM = os.getenv("ALGORITHM", "HS256")  # 加密算法RS256
access_token_expires = timedelta(minutes=10)  # 访问令牌，过期时间, seconde:单位秒
refresh_token_expires = timedelta(hours=10)  # 刷新令牌，过期时间, seconde:单位秒

# 状态码字典
STATUS_CODES = {
    "OK": 200,  # 成功
    "CREATED": 201,  # 创建成功
    "ACCEPTED": 202,  # 请求已接受，但未处理完成
    "NO_CONTENT": 204,  # 没有内容
    "MOVED_PERMANENTLY": 301,  # 永久重定向
    "FOUND": 302,  # 临时重定向
    "SEE_OTHER": 303,  # 浏览器请求其他地址
    "NOT_MODIFIED": 304,  # 未修改
    "INVALID_SIGNATURE": 400,  # 签名无效
    "UNAUTHORIZED": 401,  # 未授权
    "INVALID_PERMISSIONS": 403,  # 无效权限
    "NOT_FOUND": 404,  # 未找到
    "METHOD_NOT_ALLOWED": 405,  # 方法不允许
    "NOT_ACCEPTABLE": 406,  # 不接受
    "REQUEST_TIMEOUT": 408,  # 请求超时
    "REQUEST_ENTITY_TOO_LARGE": 413,  # 请求实体过大
    "REQUEST_URI_TOO_LONG": 414,  # 请求URI过长
    "UPGRADE_REQUIRED": 426,  # 需要升级
    "TOO_MANY_REQUESTS": 429,  # 请求过多
    "REQUEST_HEADER_FIELDS_TOO_LARGE": 431,  # 请求头字段过大
    "INTERNAL_SERVER_ERROR": 500,  # 内部服务器错误
    "SERVICE_UNAVAILABLE": 503,  # 服务不可用
}

# Error messages dictionary
ERROR_MESSAGES = {
    "OK": "请求成功.",
    "CREATED": "已创建新资源.",
    "ACCEPTED": "请求已接受，处理尚未完成.",
    "NO_CONTENT": "请求成功，但无需返回实体主体.",
    "MOVED_PERMANENTLY": "请求的资源已被永久移动.",
    "FOUND": "请求的资源临时移动.",
    "SEE_OTHER": "响应可以在其他URI下找到.",
    "NOT_MODIFIED": "文档未修改.",
    "INVALID_SIGNATURE": "签名无效.",
    "UNAUTHORIZED": "需要用户验证.",
    "INVALID_PERMISSIONS": "权限无效.",
    "NOT_FOUND": "未找到资源.",
    "METHOD_NOT_ALLOWED": "不允许使用指定的方法.",
    "NOT_ACCEPTABLE": "资源只能生成客户端不接受的响应实体.",
    "REQUEST_TIMEOUT": "请求超时.",
    "REQUEST_ENTITY_TOO_LARGE": "请求实体过大.",
    "REQUEST_URI_TOO_LONG": "请求URI过长.",
    "UPGRADE_REQUIRED": "需要升级协议.",
    "TOO_MANY_REQUESTS": "请求过多.",
    "REQUEST_HEADER_FIELDS_TOO_LARGE": "请求头字段过大.",
    "INTERNAL_SERVER_ERROR": "服务器内部错误.",
    "SERVICE_UNAVAILABLE": "服务不可用."
}


# 异常
class CustomHTTPException(HTTPException):
    def __init__(self, status_code: str, detail: Any = None, headers=None):
        status_code = STATUS_CODES.get(status_code, 500)  # Use 500 as default status code
        detail = detail or {"code": status_code}
        if isinstance(detail, dict):
            detail["code"] = status_code
        super().__init__(status_code=status_code, detail=detail, headers=headers)


def credentials_exception(err: str):
    return CustomHTTPException(
        status_code=err,
        detail=ERROR_MESSAGES.get(err, "An error occurred"),
        headers={"WWW-Authenticate": "Bearer"},
    )


#  生成token方法
def create_access_token(*, data: dict, expires_delta: timedelta = timedelta(minutes=15)):
    to_encode = data.copy()
    expire = datetime.now(timezone.utc) + expires_delta
    to_encode.update({"exp": expire})
    encoded_jwt = jwt.encode(to_encode, SECRET_KEY, algorithm=ALGORITHM)
    return encoded_jwt


# 登录验证，登录成功返回token
def login_token(username: str, password: str):
    id = GetUserid(username, password)
    if id is None:
        raise credentials_exception('UNAUTHORIZED')  # 401

    # 用id去请求用户权限
    id = str(id)
    df = GetUser_acl(id)
    if df is None:
        raise credentials_exception('INVALID_PERMISSIONS')
    df1=GetUser_proper(id)
    if df1 is None:
        raise credentials_exception('INVALID_PERMISSIONS')
    access_token = create_access_token(
        data={"sub": id}, expires_delta=access_token_expires
    )
    refresh_token = create_access_token(
        data={"sub": id}, expires_delta=refresh_token_expires
    )
    return {"code": STATUS_CODES["OK"], "msg": "success", "status": "ok",
            "data": {
                "access_token": access_token,
                "token_type": "bearer",
                "refresh_token": refresh_token,
                "username":df1['full_name'][0],
                "routes": df[df['acl_type'] == 0]['acl_name'].tolist(),
                "buttons": df[df['acl_type'] == 1]['acl_name'].tolist()}
            }


#  验证刷新token，通过刷新token获取新的token
def refresh_token_route(refresh_token: str):
    id = get_current_user(refresh_token)
    return {"code": STATUS_CODES["OK"], "msg": "success", "status": "ok",
            "data": {"access_token": create_access_token(
                data={"sub": id}, expires_delta=access_token_expires
            ), "token_type": "bearer", "refresh_token": refresh_token}}


# 用户登录成功后，后面每次请求携带令牌验证方法，验证通过后才有权限继续请求
def get_current_user(authorization: str = Header(...)):
    token = authorization.split()[1]
    try:
        payload = jwt.decode(token, SECRET_KEY, algorithms=[ALGORITHM])
        id: str = payload.get("sub")
        if id is None:
            raise credentials_exception('UNAUTHORIZED')  # 401
    except JWTError:
        raise credentials_exception('UNAUTHORIZED')  # 401
    return id
